package com.lengmomo.games.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.ui.ModelMap;

/**
 * 主要分为一下几个步骤
 * 1.定义切面（使用@Aspect注解告诉spring这个类是一个切面类 ）
 * 2.定义切点
 *
 * @author: lengmomo
 * @create: 2021/9/27
 **/
@Aspect //aop注解 告诉spring这是一个切面类
@Component
public class LoggerAdvice {

    private Logger logger = LoggerFactory.getLogger(LoggerAdvice.class);

    //1.定义切点 controller包下所有的类 中 所有的方法 不限参数个数
    @Pointcut(value = "execution( * com.lengmomo.games.controller.*.*(..))")
    public void loggerPointCut() {
    }

    //2.设置通知
    @Around("loggerPointCut()")//环绕通知
    public Object loggerAround(ProceedingJoinPoint pjp) throws Throwable {

        //获取通知的类名
        String className = pjp.getTarget().getClass().getName();
        //获取通知的方法名
        String methodName = pjp.getSignature().getName();
        //获取参数
        Object[] args = pjp.getArgs();
        ObjectMapper objectMapper = new ObjectMapper();
        long start = 0, end;
        //执行函数前打印日志
        try {
            start = System.currentTimeMillis();
            logger.info("方法调用前通知，类名：" + className + "  方法名:" + methodName + " 参数:" + objectMapper.writeValueAsString(args));
        } catch (Exception e) {
            System.out.println("参数转换失败");
        }

        //执行函数(方法)
        Object result = pjp.proceed();
        logger.info("方法调用后通知，类名：" + className + "  方法名:" + methodName + " 返回值:" + objectMapper.writeValueAsString(result));
        end = System.currentTimeMillis();
        logger.info("用时：" + (end - start) + "毫秒");
        if (result instanceof ResponseEntity) {
            ResponseEntity result1 = (ResponseEntity) result;
            ModelMap modelMap = (ModelMap) result1.getBody();
            if (modelMap != null) {
                modelMap.put("executionTime", (end - start));//放入耗时
            }
            return ResponseEntity.ok(modelMap);
        }
        return result;
    }
}
